#!/usr/bin/env python
# -*- coding:utf-8 -*- 
# Author: Jeokayne Ataier

#linux命令执行服务端
import struct
import subprocess
import socket

server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# server.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR) 重复利用端口和IP的代码 --避免重启程序时的IP或端口占用冲突
server.bind(("127.0.0.1",8881))

server.listen(10)

while True:
    conn,addr = server.accept()

    while True:
        try:
            #接收数据大小信息--4个字节 收到一个元组，解包以后第一个即为数据大小信息
            client_size = struct.unpack("i", conn.recv(4))[0]

            recv_size = 0
            cmd = b""
            while recv_size < client_size:
                recv_data = conn.recv(1024)
                cmd += recv_data
                recv_size+=len(recv_data)
            print("客户端传来需执行的命令：",cmd)
            #Linux处理空接收值的问题
            if not cmd:
                break

            '''
            接收客户端信息结束，开始执行命令+传回数据
            '''
            output_obj=subprocess.Popen(cmd.decode("utf-8"),shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
            stdout = output_obj.stdout.read() #执行命令未报错时，获得返回值（byte形式，传输无需encode） --os.system()执行后，返回0
            stderr = output_obj.stderr.read() #执行命令报错时，获得返回值（byte形式，传输无需encode） --os.system()执行后，返回非0
            '''
            客户端已经写好自动获取编码格式的代码，如果自己手动写decode，注意下面的编码：
            1.windows系统返回的byte需要用gbk解码decode
            2.Linux系统返回的byte需要用utf-8解码decode
            3.执行正确后，stderr返回值为空，反之亦然 --可优化
            '''
            if len(stdout+stderr) == 0:
                server_data = "返回值为空".encode("utf-8")
                print("返回值为空")
            else:
                server_data = stdout+stderr
                print("命令执行返回值为：",stdout+stderr)
                print("返回值长度为：",len(stdout+stderr))
            #传输数据大小信息 ---打包为4个字节
            server_size = struct.pack("i",len(server_data))
            conn.send(server_size)

            #传输数据
            conn.send(server_data)
        except ConnectionResetError:
            break

    conn.close()